//////////////////////////////////////////////////////////////////////
// SceneObj.h
//
// SHEN Fangyang
// me@shenfy.com
//
// Copyright (C) SHEN Fangyang, 2011, All rights reserved.
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
//  Brief Description
//
//	Basic scene node
//
//////////////////////////////////////////////////////////////////////
#pragma once
#include <BasisObj.h>
#include <LA/Vec3.h>
#include <vector>
#include <boost/shared_ptr.hpp>

namespace grflib
{
	namespace engine
	{
		namespace core
		{
			class CSceneObj
			{
			public:
				CSceneObj(void);
                CSceneObj(UINT priority);
				virtual ~CSceneObj(void);

				//Member accessor
				std::vector< boost::shared_ptr<IRenderable> > &GetRenderables(void) {return m_renderables;}

				const BBox<float> &GetWorldBBox(void);
                const D3DXMATRIX &GetWorldMat(void);

				bool Attach(boost::shared_ptr<IRenderable> &pRenderable);
				void Detach(boost::shared_ptr<IRenderable> &pRenderable);
				void DetachAll(void);

                //Visibility
                inline bool &Visible(void) {return m_isVisible;}

                //Priority, 0 by default
                inline const int &Priority(void) {return m_priority;}

                //Cullable
                inline bool &Cullable(void) {return m_isCullable;}

				//Traversing
				virtual void FrameMove(double fTime, float fElapsedTime);

                //Update world coord during frame move
                bool UpdateWorldCoord(void);
                void ResetUpToDateFlag(void);

				bool SetParent(char *szParent);
				bool SetParent(boost::shared_ptr<CSceneObj> &pParentObj);

                //Motion
				void MoveTo(float x, float y, float z);
				void Rotate(const D3DXMATRIX& rotMat, bool reset = true);
				void Scale(float x, float y, float z, bool reset = true);

            protected:
                //Calculate world position, matrix, bounding box.
                const D3DXMATRIX &UpdateWorldMat(void);
				void UpdateBBox(const D3DXMATRIX &mat);
				LA::CVec3<float> &UpdateWorldPos(void);

			protected:
				std::vector< boost::shared_ptr<IRenderable> > m_renderables;
				LA::CVec3<float> m_position; //mass center relative to the parent object
				LA::CVec3<float> m_scale; //x, y, z scale
				LA::CVec3<float> m_worldPos; //mass center in world coord, NOT always up to date!
				D3DXMATRIX m_rotationMat; //rotation matrix relative to the parent object
				bool m_isVisible;
                bool m_isCullable;
                const int m_priority;
				BBox<float> m_worldBBox;
                D3DXMATRIX m_worldMat;

                bool m_worldCoordUpToDate;

				//space time trade-off
				D3DXMATRIX m_tmpMat, m_tmpMat2;

				boost::shared_ptr<CSceneObj> m_pParent;
			};

		} //namespace core
	} //namespace engine
} //namespace grflib